import Vue from "vue";
import Clipboard from 'clipboard';
import AndroidSDK from '@/services/AndroidSdk';
import {Message} from 'element-ui';
import store from '@/store';
import $lodash from "lodash";
import x2js from 'x2js';
import $day from "dayjs";
import {Toast} from 'vant';
import {setTimeRangeList} from "@sc/DRCbiz/store/actions";

let $x2js = new x2js();

export function isNull(value) {
    return (value === null) || (value === undefined);
}

export function isNotNull(value) {
    return (value !== null) && (value !== undefined);
}

export function isEmptyStr(str) {
    return (str === undefined) || (!str && (str !== 0) && (str !== '0')) || (!/[^\s]/.test(str));
}

export const generateId = function () {
    return Math.floor(Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000);
};

export const deepClone = function (origin) {
    if (origin === undefined) {
        return undefined
    }

    return JSON.parse(JSON.stringify(origin))
}

export const overwriteObj = function (obj1, obj2) {  /* 浅拷贝对象属性，obj2覆盖obj1 */
    Object.keys(obj2).forEach(prop => {
        obj1[prop] = obj2[prop]
    })
}

/* 用Function对象实现eval函数功能 */
export const evalFn = function (fn, DSV = null, VFR = null) {
    let f = new Function('DSV', 'VFR', 'return ' + fn);
    return f(DSV, VFR);
};

export const addWindowResizeHandler = function (handler) {
    let oldHandler = window.onresize
    if (typeof window.onresize != 'function') {
        window.onresize = handler
    } else {
        window.onresize = function () {
            oldHandler()
            handler()
        }
    }
}

const createStyleSheet = function () {
    let head = document.head || document.getElementsByTagName('head')[0];
    let style = document.createElement('style');
    style.type = 'text/css';
    head.appendChild(style);
    return style.sheet;
}

export const insertCustomCssToHead = function (cssCode, formId = '') {
    let head = document.getElementsByTagName('head')[0]
    let oldStyle = document.getElementById('vform-custom-css')
    if (!!oldStyle) {
        head.removeChild(oldStyle)  //先清除后插入！！
    }
    if (!!formId) {
        oldStyle = document.getElementById('vform-custom-css' + '-' + formId)
        !!oldStyle && head.removeChild(oldStyle)  //先清除后插入！！
    }

    let newStyle = document.createElement('style')
    newStyle.type = 'text/css'
    newStyle.rel = 'stylesheet'
    newStyle.id = !!formId ? 'vform-custom-css' + '-' + formId : 'vform-custom-css'
    try {
        newStyle.appendChild(document.createTextNode(cssCode))
    } catch (ex) {
        newStyle.styleSheet.cssText = cssCode
    }

    head.appendChild(newStyle)
}

export const insertGlobalFunctionsToHtml = function (functionsCode, formId = '') {
    let bodyEle = document.getElementsByTagName('body')[0]
    let oldScriptEle = document.getElementById('v_form_global_functions')
    !!oldScriptEle && bodyEle.removeChild(oldScriptEle)  //先清除后插入！！
    if (!!formId) {
        oldScriptEle = document.getElementById('v_form_global_functions' + '-' + formId)
        !!oldScriptEle && bodyEle.removeChild(oldScriptEle)  //先清除后插入！！
    }

    let newScriptEle = document.createElement('script')
    newScriptEle.id = !!formId ? 'v_form_global_functions' + '-' + formId : 'v_form_global_functions'
    newScriptEle.type = 'text/javascript'
    newScriptEle.innerHTML = functionsCode
    bodyEle.appendChild(newScriptEle)
}

export const optionExists = function (optionsObj, optionName) {
    if (!optionsObj) {
        return false
    }

    return Object.keys(optionsObj).indexOf(optionName) > -1
}

export const loadRemoteScript = function (srcPath, callback) {  /*加载远程js，加载成功后执行回调函数*/
    let sid = encodeURIComponent(srcPath)
    let oldScriptEle = document.getElementById(sid)

    if (!oldScriptEle) {
        let s = document.createElement('script')
        s.src = srcPath
        s.id = sid
        document.body.appendChild(s)

        s.onload = s.onreadystatechange = function (_, isAbort) { /* 借鉴自ace.js */
            if (isAbort || !s.readyState || s.readyState === "loaded" || s.readyState === "complete") {
                s = s.onload = s.onreadystatechange = null
                if (!isAbort) {
                    callback()
                }
            }
        }
    }
}

export function traverseFieldWidgets(widgetList, handler, parent = null) {
    if (!widgetList) {
        return
    }

    widgetList.map(w => {
        if (w.formItemFlag) {
            handler(w, parent)
        } else if (w.type === 'grid') {
            w.cols.map(col => {
                traverseFieldWidgets(col.widgetList, handler, w)
            })
        } else if (w.type === 'table') {
            w.rows.map(row => {
                row.cols.map(cell => {
                    traverseFieldWidgets(cell.widgetList, handler, w)
                })
            })
        } else if (w.type === 'tab') {
            w.tabs.map(tab => {
                traverseFieldWidgets(tab.widgetList, handler, w)
            })
        } else if (w.type === 'sub-form') {
            traverseFieldWidgets(w.widgetList, handler, w)
        } else if (w.category === 'container') {  //自定义容器
            traverseFieldWidgets(w.widgetList, handler, w)
        }
    })
}

export function traverseContainerWidgets(widgetList, handler) {
    if (!widgetList) {
        return
    }

    widgetList.map(w => {
        if (w.category === 'container') {
            handler(w)
        }

        if (w.type === 'grid') {
            w.cols.map(col => {
                traverseContainerWidgets(col.widgetList, handler)
            })
        } else if (w.type === 'table') {
            w.rows.map(row => {
                row.cols.map(cell => {
                    traverseContainerWidgets(cell.widgetList, handler)
                })
            })
        } else if (w.type === 'tab') {
            w.tabs.map(tab => {
                traverseContainerWidgets(tab.widgetList, handler)
            })
        } else if (w.type === 'sub-form') {
            traverseContainerWidgets(w.widgetList, handler)
        } else if (w.category === 'container') {  //自定义容器
            traverseContainerWidgets(w.widgetList, handler)
        }
    })
}

export function traverseAllWidgets(widgetList, handler) {
    if (!widgetList) {
        return
    }

    widgetList.map(w => {
        handler(w)

        if (w.type === 'grid') {
            w.cols.map(col => {
                handler(col)
                traverseAllWidgets(col.widgetList, handler)
            })
        } else if (w.type === 'table') {
            w.rows.map(row => {
                row.cols.map(cell => {
                    handler(cell)
                    traverseAllWidgets(cell.widgetList, handler)
                })
            })
        } else if (w.type === 'tab') {
            w.tabs.map(tab => {
                traverseAllWidgets(tab.widgetList, handler)
            })
        } else if (w.type === 'sub-form') {
            traverseAllWidgets(w.widgetList, handler)
        } else if (w.category === 'container') {  //自定义容器
            traverseAllWidgets(w.widgetList, handler)
        }
    })
}

function handleWidgetForTraverse(widget, handler) {
    if (!!widget.category) {
        traverseFieldWidgetsOfContainer(widget, handler)
    } else if (widget.formItemFlag) {
        handler(widget)
    }
}

/**
 * 遍历容器内的字段组件
 * @param con
 * @param handler
 */
export function traverseFieldWidgetsOfContainer(con, handler) {
    if (con.type === 'grid') {
        con.cols.forEach(col => {
            col.widgetList.forEach(cw => {
                handleWidgetForTraverse(cw, handler)
            })
        })
    } else if (con.type === 'table') {
        con.rows.forEach(row => {
            row.cols.forEach(cell => {
                cell.widgetList.forEach(cw => {
                    handleWidgetForTraverse(cw, handler)
                })
            })
        })
    } else if (con.type === 'tab') {
        con.tabs.forEach(tab => {
            tab.widgetList.forEach(cw => {
                handleWidgetForTraverse(cw, handler)
            })
        })
    } else if (con.type === 'sub-form') {
        con.widgetList.forEach(cw => {
            handleWidgetForTraverse(cw, handler)
        })
    } else if (con.category === 'container') {  //自定义容器
        con.widgetList.forEach(cw => {
            handleWidgetForTraverse(cw, handler)
        })
    }
}

/**
 * 获取所有字段组件
 * @param widgetList
 * @returns {[]}
 */
export function getAllFieldWidgets(widgetList) {
    if (!widgetList) {
        return []
    }

    let result = []
    let handlerFn = (w) => {
        result.push({
            type: w.type,
            name: w.options.name,
            field: w
        })
    }
    traverseFieldWidgets(widgetList, handlerFn)

    return result
}

/**
 * 获取所有容器组件
 * @param widgetList
 * @returns {[]}
 */
export function getAllContainerWidgets(widgetList) {
    if (!widgetList) {
        return []
    }

    let result = []
    let handlerFn = (w) => {
        result.push({
            type: w.type,
            name: w.options.name,
            container: w
        })
    }
    traverseContainerWidgets(widgetList, handlerFn)

    return result
}

export function copyToClipboard(content, clickEvent, $message, successMsg, errorMsg) {
    const clipboard = new Clipboard(clickEvent.target, {
        text: () => content
    })

    clipboard.on('success', () => {
        $message.success(successMsg)
        clipboard.destroy()
    })

    clipboard.on('error', () => {
        $message.error(errorMsg)
        clipboard.destroy()
    })

    clipboard.onClick(clickEvent)
}

export function getQueryParam(variable) {
    let query = window.location.search.substring(1);
    let vars = query.split("&")
    for (let i = 0; i < vars.length; i++) {
        let pair = vars[i].split("=")
        if (pair[0] === variable) {
            return pair[1]
        }
    }

    return undefined;
}

export function getDefaultFormConfig() {
    return {
        devType: false,
        modelName: 'formData',
        refName: 'vForm',
        rulesName: 'rules',
        labelWidth: 80,
        labelPosition: 'left',
        size: '',
        labelAlign: 'label-left-align',
        cssCode: '',
        customClass: [],
        functions: '',  //全局函数
        layoutType: 'PC',
        jsonVersion: 3,
        onFormCreated: '',
        onFormMounted: '',
        onFormDataChange: '',
        parentInfo: {
            backgroundColor: 'rgba(255,255,255,0)',
            backgroundImage: '',
            compBiz: false,
        },
        viewName: ''
    }
}

export function buildDefaultFormJson() {
    return {
        widgetList: [],
        formConfig: deepClone(getDefaultFormConfig())
    }
}

export function buildParentApi() {
    return {
        executeParentMethod: function (key, data = Object(), keyInfo) {
            switch (key) {
                /*前端->通知安卓写入日志*/
                case 'writeLog':
                    AndroidSDK.WebLogAction(data);
                    break;
                /*前端->通知安卓请求第三方*/
                case 'axiosRep':
                    store.dispatch('layout/setLoading');
                    AndroidSDK.WebToAndroidRep(data, keyInfo);
                    break;
                /*前端->通知安卓打开扫码*/
                case 'openScan':
                    console.log(`openScan:${JSON.stringify(data)}`)
                    AndroidSDK.WebToAndroidOpenScan(data);
                    break;
                /*前端->通知关闭扫码*/
                case 'closeScan':
                    console.log(`closeScan:${JSON.stringify(data)}`)
                    AndroidSDK.WebToAndroidCloseScan(data);
                    break;
                /*前端->电子医保码*/
                case 'MICode':
                    console.log(`MICode:${JSON.stringify(data)}`)
                    AndroidSDK.WebToAndroidMICode(data);
                    break;
                /*前端->获取设备*/
                case 'deviceInfo':
                    console.log(`deviceInfo:${JSON.stringify(data)}`)
                    AndroidSDK.WebToAndroidDevInfo(data);
                    break;
            }
        },
    }
}


// 安卓回传第三方接口返回的数据
export function AndroidToWeb(key, data) {
    let dataInfo;
    let steps = store.getters['DRCbiz/getStepsInfo'];
    switch (key) {
        case "deviceInfo":
            let devInfo = Object();
            try {
                dataInfo = JSON.parse(data)
            } catch (e) {
                dataInfo = Object();
            }
            let msgContent = dataInfo?.msgContent;
            Reflect.set(devInfo, 'screenIp', (msgContent?.screenIp));
            Reflect.set(devInfo, 'screenId', (msgContent?.screenId));
            localStorage.setItem('deviceInfo', JSON.stringify(devInfo))
            break
        /**
         *  @desc  获取卡片编号
         *  cardInfoCallBack:卡片编号
         **/
        case "cardInfoCallBack":
            dataInfo = data;
            try {
                let cardId = dataInfo?.msgContent?.cardId;
                let cardIdOriginal = dataInfo?.msgContent?.cardIdOriginal;
                let cardTypeInfo = $lodash.cloneDeep(store.getters['DRCbiz/getCardTypeInfo']);
                Reflect.set(cardTypeInfo, 'cardNo', cardId);                           //电子凭证
                Reflect.set(cardTypeInfo, 'cardInfo', cardIdOriginal); //卡信息
                store.dispatch('DRCbiz/setCardTypeInfo', cardTypeInfo);
            } catch (e) {
                console.log(e)
            } finally {
                buildParentApi().executeParentMethod('closeScan');
            }
            break;
        /**
         *  @desc  获取患者信息
         *  QueryPatient:获取患者信息
         **/
        case 'QueryPatient':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setPatientInfo', dataInfo);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                // 当患者数据请求异常重新打开扫码功能
                console.log(e)
                buildParentApi().executeParentMethod('openScan')
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  允许取号的列表
         *  QueryRegisterRecord:允许取号的仓库数据
         **/
        case 'QueryRegisterRecord':
            dataInfo = respClear(data);
            if (!$lodash.isArray(dataInfo.result)) {
                Reflect.set(dataInfo, 'result', [dataInfo.result])
            }
            console.log(dataInfo)
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setTakeNumberList', dataInfo);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  取消预约的号
         *  QueryPatient: 取消预约的号
         **/
        case 'CancelAppointOrRegister':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = Object();
                    Reflect.set(info, 'stateInfo', 'success');
                    Reflect.set(info, 'header', '取消预约成功');
                    Reflect.set(info, 'describe', `您已于${$day().format('HH:mm:ss')}取消预约信息`);
                    store.dispatch('DRCbiz/setMessageInfo', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  确定预约取号
         *  TakeAccount: 确定预约取号
         **/
        case 'TakeAccount':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = Object();
                    Reflect.set(info, 'stateInfo', 'success');
                    Reflect.set(info, 'header', '取号成功');
                    Reflect.set(info, 'describe', `您已于${$day().format('HH:mm:ss')}取号成功`);
                    store.dispatch('DRCbiz/setMessageInfo', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  获取科室
         *  QueryDept: 获取科室
         **/
        case 'QueryDept':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setDeptOptions', dataInfo);
                    store.dispatch('DRCbiz/setAppointRegInfo', Object());
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  医生排班(List)
         *  QuerySchedule: 医生排班
         **/
        case 'QuerySchedule':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setDrScheduleList', dataInfo);
                    // 判断当切业务类型以及号源类型 ****挂号并且普通患者步切换视图****
                    let bizInfo = store.getters['DRCbiz/getBizInfo'];
                    let OPTypeInfo = store.getters['DRCbiz/getOPTypeInfo'];
                    if (((bizInfo?.routeName === 'register') && (OPTypeInfo?.id === 1))) {
                        store.dispatch('DRCbiz/setStepsInfo', steps);
                        store.dispatch('DRCbiz/setAutoPreAppointReg', true);
                    } else {
                        store.dispatch('DRCbiz/setStepsInfo', ++steps);
                        store.dispatch('DRCbiz/setAutoPreAppointReg', false)
                    }
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  预结算
         *  preAppointReg: 预结算
         **/
        case 'preAppointReg':
            dataInfo = respClear2(data);
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setAppointRegInfo', dataInfo);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  结算(List)
         *  AppointReg: 结算
         **/
        case 'AppointReg':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = Object();
                    Reflect.set(info, 'stateInfo', 'success');
                    Reflect.set(info, 'header', '取号成功');
                    Reflect.set(info, 'describe', `您已于${$day().format('HH:mm:ss')}挂号成功`);
                    store.dispatch('DRCbiz/setMessageInfo', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         *  @desc  时间段(List)
         *  querySourceList: 时间段
         **/
        case 'querySourceList':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    store.dispatch('DRCbiz/setTimeRangeList', dataInfo);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         * @name 建档
         * @author zk
         */
        case 'CreateCardAddPosit':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = Object();
                    Reflect.set(info, 'stateInfo', 'success');
                    Reflect.set(info, 'header', '建档成功');
                    Reflect.set(info, 'describe', `您已成功于${$day().format('HH:mm:ss')}建档`);
                    store.dispatch('DRCbiz/setMessageInfo', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
                store.dispatch('layout/cancelLoading');
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break;
        /**
         * @name 获取待缴费明细
         * @author zk
         */
        case 'QueryCostDetail':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    store.dispatch('DRCbiz/setWaitPayTheFees', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 缴费预结算
         * @author zk
         */
        case 'preOpPay':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    store.dispatch('DRCbiz/setWaitPayTheFees', info);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 获取药品信息查询
         * @author zk
         */
        case 'QueryMedicinesInfo':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    store.dispatch('DRCbiz/setDrugInformationDetailsList', info.result);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 项目信息查询
         * @author zk
         */
        case 'QueryCostInfo':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    store.dispatch('DRCbiz/setItemList', info.result);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 已缴费明细查询
         * @author zk
         */
        case 'QueryFeeDetailRecord':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    // store.dispatch('DRCbiz/setWaitPayTheFees', info);
                    // store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 住院患者信息
         * @author zk
         */
        case 'ZYQueryPatientInfo':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    console.log('info.resultinfo.result', info.result, info.result && info.result[0])
                    if (info.result && info.result[0]) {
                        console.log(111111111)
                        store.dispatch('DRCbiz/setInpatientInformation', info.result[0]);
                    } else {
                        store.dispatch('DRCbiz/setInpatientInformation', {});
                    }
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break
        /**
         * @name 住院一日清单查询
         * @author zk
         */
        case 'ZYQueryBillDetail':
            dataInfo = respClear(data);
            try {
                if (dataInfo.state) {
                    let info = dataInfo
                    console.log('infoinfoinfo', info)
                    // store.dispatch('DRCbiz/setWaitPayTheFees', info);
                    store.dispatch('DRCbiz/setOneDayHospitalizationList', info.result);
                    store.dispatch('DRCbiz/setStepsInfo', ++steps);
                }
            } catch (e) {
                console.log(e)
            } finally {
                store.dispatch('layout/cancelLoading');
            }
            break

    }
}

// 清洗服务端返回的数据(服务器获取数据&操作状态)
export function respClear(data) {
    let {Response} = $x2js.xml2js(data);

    let {ResultCode, ResultData, ErrorMsg} = Response;
    let info = Object();
    if (parseInt(ResultCode) === 0) {
        let result = (ResultData?.RecordList?.RecordInfo) || Object();
        Reflect.set(info, 'result', result);
        Reflect.set(info, 'state', true);
    } else {
        Reflect.set(info, 'state', false);
        Toast({
            message: `很抱歉，${ErrorMsg}`,
            position: 'bottom',
            type: 'fail',
            forbidClick: true,
            duration: 3000
        });
    }
    return info;
}


export function respClear2(data) {
    let {Response} = $x2js.xml2js(data);
    let {ResultCode, ResultData, ErrorMsg} = Response;
    let info = Object();
    if (parseInt(ResultCode) === 0) {
        let result = ResultData || Object();
        Reflect.set(info, 'result', result);
        Reflect.set(info, 'state', true);
    } else {
        Reflect.set(info, 'state', false);
        Toast({
            message: `很抱歉，${ErrorMsg}`,
            position: 'bottom',
            type: 'fail',
            forbidClick: true,
            duration: 3000
        });
    }
    return info;
}